﻿#include <tchar.h>
#include "OnlineUserList.h"

// 函数声明
static void OnlineUserList_Delete(OnlineUserList*);
static void OnlineUserList_AddSocket(OnlineUserList*, SOCKET);
static SOCKET OnlineUserList_Find(OnlineUserList*, LPCTSTR);
static OnlineUser* OnlineUserList_FindBySocket(OnlineUserList*, SOCKET, OnlineUser**);
static void OnlineUserList_RemoveAll(OnlineUserList*);
static void OnlineUserList_RemoveByName(OnlineUserList*, LPCTSTR);
static void OnlineUserList_RemoveBySocket(OnlineUserList*, SOCKET);
static void OnlineUserList_SetAt(OnlineUserList*, SOCKET, LPCTSTR);

/**
 * 创建在线用户列表。
 * @return 在线用户列表
 */
OnlineUserList* New_OnlineUserList() {
    OnlineUserList* list = (OnlineUserList*)calloc(1, sizeof(OnlineUserList));

    // 初始化函数
    list->deleteSelf = OnlineUserList_Delete;
    list->addSocket = OnlineUserList_AddSocket;
    list->find = OnlineUserList_Find;
    list->findBySocket = OnlineUserList_FindBySocket;
    list->removeAll = OnlineUserList_RemoveAll;
    list->removeByName = OnlineUserList_RemoveByName;
    list->removeBySocket = OnlineUserList_RemoveBySocket;
    list->setAt = OnlineUserList_SetAt;

    return list;
}

/**
 * 删除在线用户列表。
 * @param list  在线用户列表
 */
static void OnlineUserList_Delete(OnlineUserList* list) {
    OnlineUserList_RemoveAll(list);
    free(list);
}

/**
 * 添加用户套接字。
 * @param list  在线用户列表
 * @param sock  用户套接字
 */
static void OnlineUserList_AddSocket(OnlineUserList* list, SOCKET sock) {
    // 生成结点
    OnlineUser* node = (OnlineUser*)calloc(1, sizeof(OnlineUser));
    node->sock = sock;

    if (list->mHead == NULL) {
        // 如果头结点为空，生成的结点作为头结点
        list->mHead = node;
    } else if (list->mCauda == NULL) {
        // 如果尾结点为空，生成的结点作为尾结点
        list->mCauda = node;
        list->mHead->next = list->mCauda;
    } else {
        // 如果头、尾结点都不为空，生成的结点作为尾结点的下一个结点
        list->mCauda->next = node;
        list->mCauda = node;
    }
}

/**
 * 查找用户。
 * @param list      在线用户列表
 * @param username  用户名
 * @return 用户
 */
static SOCKET OnlineUserList_Find(OnlineUserList* list, LPCTSTR username) {
    BOOL found = FALSE;
    OnlineUser* currentUser = list->mHead;

    // 遍历所有在线用户，找到用户名
    while (currentUser != NULL) {
        found = !(_tcscmp(currentUser->username, username));
        if (found) {
            return currentUser->sock;
        }
        currentUser = currentUser->next;
    }
    return INVALID_SOCKET;
}

/**
 * 查找用户。
 * @param list          在线用户列表
 * @param sock          用户套接字
 * @param previousUser  上一个用户
 * @return 用户
 */
static OnlineUser* OnlineUserList_FindBySocket(OnlineUserList* list, SOCKET sock, OnlineUser** previousUser) {
    BOOL found = FALSE;
    OnlineUser* currentUser = list->mHead;

    // 遍历所有在线用户，找到用户名
    while (currentUser != NULL) {
        found = (currentUser->sock == sock);
        if (found) {
            return currentUser;
        }
        if (previousUser != NULL) {
            *previousUser = currentUser;
        }
        currentUser = currentUser->next;
    }
    return currentUser;
}

/**
 * 删除所有用户。
 * @param list  在线用户列表
 */
static void OnlineUserList_RemoveAll(OnlineUserList* list) {
    OnlineUser* currentUser = list->mHead;

    // 删除所有在线用户
    while (currentUser != NULL) {
        list->mHead = list->mHead->next;
        free(currentUser);
        currentUser = list->mHead;
    }

    // 头尾结点置空
    list->mHead = list->mCauda = NULL;
}

/**
 * 删除一个用户。
 * @param list      在线用户列表
 * @param username  用户名
 */
static void OnlineUserList_RemoveByName(OnlineUserList* list, LPCTSTR username) {
    OnlineUser* previousUser = NULL;
    OnlineUser* currentUser = list->mHead;
    BOOL found = FALSE;

    // 遍历所有在线用户
    while (currentUser != NULL) {
        found = !(_tcscmp(currentUser->username, username));
        if (found) {
            currentUser->username[0] = '\0';
            return;
        }
        previousUser = currentUser;
        currentUser = currentUser->next;
    }
}

/**
 * 删除一个用户。
 * @param list  在线用户列表
 * @param sock  用户套接字
 */
static void OnlineUserList_RemoveBySocket(OnlineUserList* list, SOCKET sock) {
    OnlineUser* previousUser = NULL;
    OnlineUser* currentUser = OnlineUserList_FindBySocket(list, sock, &previousUser);

    // 将该用户从在线列表移除
    if (previousUser == NULL) {
        list->mHead = currentUser->next;
    } else {
        previousUser->next = currentUser->next;
    }
    if (currentUser == list->mCauda) {
        list->mCauda = NULL;
    }
    free(currentUser);
}

/**
 * 设置用户名。
 * @param list      在线用户列表
 * @param sock      套接字
 * @param username  用户名
 */
static void OnlineUserList_SetAt(OnlineUserList* list, SOCKET sock, LPCTSTR username) {
    OnlineUser* onlineUser = OnlineUserList_FindBySocket(list, sock, NULL);
    if (onlineUser == NULL) {
        return;
    }
    _tcscpy_s(onlineUser->username, USERNAME_BUF_LEN, username);
}
